

package org.jma.app.ewisdom;

import java.io.File;
import java.util.HashMap;

import org.jma.app.ewisdom.entities.User;
import org.jma.app.ewisdom.security.AccessRoules;
import org.jma.app.ewisdom.services.SrvFileManager;
import org.jma.app.ewisdom.services.SrvGroupManager;
import org.jma.app.ewisdom.services.SrvUserManager;
import org.jma.app.ewisdom.services.utils.LuceneIndexer;
import org.jma.app.ewisdom.services.utils.queries.QueryReceiver;
import org.jma.lib.soap.SOAPApplication;
import org.jma.lib.soap.events.SOAPSessionEvent;
import org.jma.lib.soap.sessions.SOAPSession;
import org.jma.lib.soap.sessions.SOAPSessionException;
import org.jma.lib.soap.sessions.SOAPSessionFilter;
import org.jma.lib.soap.sessions.SOAPSessionListener;

import easypastry.cast.CastHandler;
import easypastry.core.PastryConnection;
import easypastry.core.PastryKernel;
import easypastry.dht.DHTException;
import easypastry.dht.DHTHandler;
import easypastry.util.Utilities;

/**
 * <code>Ewisdom</code> class is the main class of the project. Its constructor calls the {@link SOAPApplication} superclass 
 * constructor and appends itself as a {@link SOAPSessionListener} and {@link SOAPSessionFilter}, it means on every time a SOAPsession 
 * is initiated or destroyed the methods <code>SOAPSessionInitiated</code> and <code>SOAPSessionTerminated</code> will be called.<br>
 * <code>Ewisdom</code> class implements <code>SOAPSessionFilter</code>, before a service is called the method <code>doFilter</code> is executed.
 * This class creates the default user and group if it does not exist and creates the <code>easyPastry</code> connection.
 * Also configures the {@link SrvFileManager} and {@link LucenIndexer} options.<br>
 * @author Jesus Mari, jesmari@ono.com
 * @version 1.0
 * @since 1.0
 */
public class Ewisdom extends SOAPApplication implements SOAPSessionListener, SOAPSessionFilter{
	private PastryConnection con=null;
	private DHTHandler dhtSessions;
	private AccessRoules ar = new AccessRoules();
	
	public Ewisdom(){
		super();
		//this SOAP application will be the Session creation/finalization listener
		//and filter too, it'll filter the invalid attempts to access to the application
		this.getSOAPProxy().addSOAPSessionListener(this);
		this.getSOAPProxy().addSOAPSessionFilter(this);
		try {
			PastryKernel.init(new File(".").getCanonicalPath()+"/easypastry-config.xml");		
			con = PastryKernel.getPastryConnection();
			
			
			
			
			dhtSessions = PastryKernel.getDHTHandler(Utilities.generateStringHash("p2p://org.jma.app.ewisdom.sessions"));

			//creates default root user
			String root = "root";
			HashMap parameters =new HashMap();
			parameters.put("userName","root");
			parameters.put("password", "root");
			parameters.put("groupName", "wheel");
			parameters.put("description", "Group for administrative tasks");
			SrvUserManager us = new SrvUserManager();
			SrvGroupManager gs= new SrvGroupManager();
			User u = us.getUserByUserName(parameters);
			//Creates default root user with password 'root'
			//Creates the administrators group 'wheel'
			if(u==null){
				us.addUser(parameters);
				gs.addGroup(parameters);
				gs.joinUserToGroup(parameters);
			}
			//define AccessRoules for Contents and Files
			ar.add("ADD_CONTENTS");
			ar.add("READ_CONTENTS");
			ar.add("REMOVE_CONTENTS");
			ar.add("MODIFY_CONTENTS");
			ar.add("CHANGE_CONTENT_ROULES");
			
			
		} catch(Exception e){
			e.printStackTrace();
		}	
	}
	public Ewisdom(String args[]){
		this();
		//Service File Manager settings
		SrvFileManager.REPOSITORY=(String)args[0];	
		SrvFileManager.FIRST_AVAILABLE_PORT=Integer.parseInt(args[1]);
		SrvFileManager.SERVER_PORT=Integer.parseInt(args[2]);
		SrvFileManager.HTTP_SERVER_FOLDER=(String)args[3];
		//Lucene Indexer settings
		LuceneIndexer.INDEX_REPOSITORY=(String)args[4];
		LuceneIndexer.MAX_RESULTS=Integer.parseInt(args[5]);
	}
	
	AccessRoules getAccessRoules(){
		return ar;
	}
	
	public boolean SOAPSessionInitiated(SOAPSessionEvent event) throws SOAPSessionException {
		String userName = event.getSession().getUserName();
		String password = event.getSession().getPassword();
		
		
		String ip = event.getRequest().getInetAddress().getHostAddress();
		try {
			SOAPSession s =(SOAPSession) dhtSessions.get(userName);
			if (s!=null) throw new SOAPSessionException("User is already logged");
			
			HashMap parameters =new HashMap();
			parameters.put("userName",userName);
			SrvUserManager us = new SrvUserManager();
			User u = us.getUserByUserName(parameters);
			//Check User password
			if(u==null) throw new SOAPSessionException("User doesn't exist");
			
			if (password.equals(u.getPassword())||
					u.getPassword()==null){
				//Password is OK, it stores the session and creates the QueryReceiver
				dhtSessions.put(userName,s);

				CastHandler cast = PastryKernel.getCastHandler();
				QueryReceiver qr=new QueryReceiver(SrvFileManager.MESSAGING_GROUP);
				cast.addDeliverListener(SrvFileManager.MESSAGING_GROUP, qr);
				event.getSession().put("queryReceiver", qr);
				return true;
			}
		} catch (Exception e) {
			throw new SOAPSessionException("User can't be logged because an internal error");
		}
		throw new SOAPSessionException("Invalid UserName or Password");
	}


	public void SOAPSessionTerminated(SOAPSessionEvent event)  throws SOAPSessionException {
		// removes DHT Session.
		try {
			SOAPSession s = (SOAPSession)dhtSessions.get(event.getSession().getUserName());
			//session could be ended by timeout
			if (s!=null) dhtSessions.remove(event.getSession().getUserName());
		} catch (DHTException e) {
			throw new SOAPSessionException("Session "+ event.getSession().toString()+" can't be removed");
		}
	}
	@Override
	public void doFilter(SOAPSessionEvent event) throws SOAPSessionException {
		// TODO Auto-generated method stub
		if (event.getSession()==null) throw new SOAPSessionException("Session closed");

		
	}
}
